package web

import (
	"errors"
	"fmt"
	"gitee.com/go-boot/boot-interfaces/ihttp"
	"strings"
)

func (engine *HttpEngine) port() string {
	return fmt.Sprintf(":%d", engine.Port)
}

func (engine *HttpEngine) getPool() ihttp.IHttpContext {
	ctx := engine.pool.Get()
	if ctx == nil {
		ctx = NewContext(engine.log)
	}
	return ctx.(ihttp.IHttpContext)
}

// before 执行拦截器前置方法
func (engine *HttpEngine) before(ctx ihttp.IHttpContext) error {
	// 执行拦截器前置方法
	if len(engine.interceptors) > 0 {
		for _, routerInterceptor := range engine.interceptors {
			if !routerInterceptor.Before(ctx) {
				engine.log.WarnF("请求[%s:%s] => 前置[%s]验证失败", ctx.Method(), ctx.Path(), routerInterceptor.Name())
				return errors.New(routerInterceptor.Name() + "前置Handler验证失败")
			}
		}
	}
	return nil
}

// after 执行拦截器后置方法
func (engine *HttpEngine) after(ctx ihttp.IHttpContext) error {
	// 执行拦截器后置方法
	if len(engine.interceptors) > 0 {
		for _, routerInterceptor := range engine.interceptors {
			if !routerInterceptor.After(ctx) {
				engine.log.WarnF("请求[%s:%s] => 后置[%s]验证失败", ctx.Method(), ctx.Path(), routerInterceptor.Name())
				return errors.New(routerInterceptor.Name() + "后置Handler验证失败")
			}
		}
	}
	return nil
}

func (engine *HttpEngine) matchPath(ctx ihttp.IHttpContext) error {

	var executeHandler = func() error {
		defer func() {
			if err := recover(); err != nil {
				engine.log.ErrorF("请求[%s:%s] => 执行发生异常：%s", ctx.Method(), ctx.Path(), err)
				ctx.Response().Json(500, err)
			}
		}()
		engine.Match(ctx)(ctx)
		return nil
	}

	// 执行拦截器前置方法
	if err := engine.before(ctx); err != nil {
		engine.beforeInterceptor(ctx)
		return nil
	}
	_ = executeHandler()
	// 执行拦截器后置方法
	if err := engine.after(ctx); err != nil {
		engine.afterInterceptor(ctx)
		return nil
	}
	return nil
}

func (engine *HttpEngine) putPool(ctx ihttp.IHttpContext) {
	engine.pool.Put(ctx)
}

// printUrlPath 输出请求路径
func (engine *HttpEngine) printUrlPath() {

	var traversePaths func(router ihttp.IRouter, path []string)

	traversePaths = func(router ihttp.IRouter, path []string) {

		path = append(path, router.Path())

		for _, item := range router.Methods() {
			engine.log.InfoF("[%6s] => [/%s]", strings.ToLower(item), strings.Join(path, "/"))
		}

		if len(router.Children()) == 0 {
			return
		}
		for _, r := range router.Children() {
			traversePaths(r, path)
		}
		// 回溯
		path = path[:len(path)-1]
	}

	for _, v := range engine.tree {
		traversePaths(v, []string{})
	}
}

// printInterceptor 输出拦截器
func (engine *HttpEngine) printInterceptor() {
	for _, interceptor := range engine.interceptors {
		engine.log.InfoF("加载拦截器: %s", interceptor.Name())
	}
}
